// 在文件开头定义配置
const SSE_CONFIG = {
    MAX_RETRIES: 5,
    RETRY_DELAY: 2000,
    ENDPOINT: '/sse/stream',
    SIGNATURE_ENDPOINT: '/sse/gensignature'
};

/**
 * 增强型SSE连接类
 * 负责处理底层的SSE连接、重连和事件监听
 */
class EnhancedSSE {
    /**
     * 连接状态常量
     */
    static CONNECTION_STATES = {
        CLOSED: 'closed',
        CONNECTING: 'connecting',
        CONNECTED: 'connected',
        RECONNECTING: 'reconnecting',
        FAILED: 'failed'
    };

    /**
     * 创建增强型SSE连接
     * @param {string} url - SSE连接URL
     * @param {Object} options - 配置选项
     * @param {number} options.maxRetries - 最大重试次数
     * @param {number} options.retryDelay - 重试基础延迟(毫秒)
     * @param {number} options.maxDelay - 最大重试延迟(毫秒)
     * @param {number} options.backoffFactor - 重试延迟增长系数
     * @param {Function} options.onOpen - 连接打开回调
     * @param {Function} options.onError - 连接错误回调
     * @param {Function} options.onMaxRetries - 达到最大重试次数回调
     * @param {Function} options.onStateChange - 连接状态变更回调
     */
    constructor(url, options = {}) {
        this.url = url;
        this.options = {
            maxRetries: options.maxRetries || SSE_CONFIG.MAX_RETRIES,
            retryDelay: options.retryDelay || SSE_CONFIG.RETRY_DELAY,
            maxDelay: options.maxDelay || 10000,
            backoffFactor: options.backoffFactor || 1.5,
            ...options
        };
        
        this.listeners = {};
        this.retryCount = 0;
        this._connecting = false;
        this._aborted = false;
        this._connectingStartTime = null;
        
        // 设置初始状态
        this._connectionState = EnhancedSSE.CONNECTION_STATES.CLOSED;

        // 立即连接
        this.connect();
    }

    /**
     * 获取当前连接状态
     */
    get connectionState() {
        return this._connectionState;
    }

    /**
     * 更新连接状态
     */
    _changeState(newState) {
        const oldState = this._connectionState;
        this._connectionState = newState;
        
        if (typeof this.options.onStateChange === 'function') {
            this.options.onStateChange(newState, oldState);
        }
        
        // 也触发自定义事件供外部监听
        const event = new CustomEvent('sse-state-change', {
            detail: { state: newState, previousState: oldState }
        });
        document.dispatchEvent(event);
    }

    /**
     * 建立SSE连接
     */
    connect() {
        // 防止重入和并发连接尝试
        if (this._connecting) return;

        this._connecting = true;
        this._connectingStartTime = new Date().getTime();
        this._changeState(EnhancedSSE.CONNECTION_STATES.CONNECTING);
        
        try {
            
            // 如果已经被中止，不再尝试连接
            if (this._aborted) {
                return;
            }

            // 关闭现有连接
            this._closeEventSource();

            // 更新状态
            this._changeState(EnhancedSSE.CONNECTION_STATES.CONNECTING);
            
            // 创建新连接
            this.eventSource = new EventSource(this.url);
            this._connectingStartTime = Date.now();
            
            // 连接成功事件
            this.eventSource.onopen = () => {
                this._connectingStartTime = null;
                this.retryCount = 0;
                this._changeState(EnhancedSSE.CONNECTION_STATES.CONNECTED);
                
                if (typeof this.options.onOpen === 'function') {
                    this.options.onOpen();
                }
            };
            
            // 连接错误事件
            this.eventSource.onerror = (error) => {
                // 记录连接错误时间
                const now = Date.now();
                
                // 如果连接已关闭或连接中状态持续过长，触发重连
                if (this.eventSource.readyState === EventSource.CLOSED || 
                    (this.eventSource.readyState === EventSource.CONNECTING && 
                     this._connectingStartTime && 
                     (now - this._connectingStartTime > 5000))) {
                    
                    // 使用重连策略
                    this._reconnect();
                } else if (this.eventSource.readyState === EventSource.CONNECTING && !this._connectingStartTime) {
                    // 记录开始连接的时间
                    this._connectingStartTime = now;
                }
                
                if (typeof this.options.onError === 'function') {
                    this.options.onError(error);
                }
            };

            // 原始消息处理
            this.eventSource.onmessage = (event) => {
                try {
                    console.log('SSE原始消息:', event);
                    const data = JSON.parse(event.data);
                    
                    // 直接分发原始消息事件，不做任何业务处理
                    const rawEvent = new CustomEvent('sse-raw-message', { 
                        detail: { 
                            eventType: 'message',
                            eventData: event.data,
                            parsedData: data
                        }
                    });
                    document.dispatchEvent(rawEvent);
                } catch (err) {
                    console.error('处理SSE原始消息出错:', err);
                }
            };
            
            // 重新添加所有事件监听器
            this._reattachEventListeners();
            
        } catch (error) {
            console.error('建立SSE连接时发生错误:', error);
            this._reconnect();
        } finally {
            this._connecting = false;
        }
    }

    /**
     * 添加通用消息监听器 (新增方法)
     * @param {Function} callback - 处理所有SSE消息的回调函数
     * @returns {Function} - 返回移除该监听器的函数
     */
    addMessageListener(callback) {
        const handler = (event) => callback(event.detail);
        document.addEventListener('sse-message', handler);
        
        // 返回移除监听器的函数
        return () => document.removeEventListener('sse-message', handler);
    }

    /**
     * 添加特定类型消息监听器 (新增方法)
     * @param {string} messageType - 消息类型 
     * @param {Function} callback - 处理该类型消息的回调函数
     * @returns {Function} - 返回移除该监听器的函数
     */
    addTypedMessageListener(messageType, callback) {
        const handler = (event) => callback(event.detail);
        const eventName = `sse-${messageType}`;
        document.addEventListener(eventName, handler);
        
        // 返回移除监听器的函数
        return () => document.removeEventListener(eventName, handler);
    }

    /**
     * 关闭内部EventSource连接
     */
    _closeEventSource() {
        if (this.eventSource) {
            try {
                // 移除所有事件监听器
                Object.keys(this.listeners).forEach(eventName => {
                    this.listeners[eventName].forEach(callback => {
                        this.eventSource.removeEventListener(eventName, callback);
                    });
                });
                
                this.eventSource.close();
            } catch (err) {
                console.error('关闭SSE连接时出错:', err);
            } finally {
                this.eventSource = null;
            }
        }
    }

    /**
     * 重新附加所有事件监听器
     */
    _reattachEventListeners() {
        if (!this.eventSource) return;
        
        Object.keys(this.listeners).forEach(eventName => {
            this.listeners[eventName].forEach(callback => {
                this.eventSource.addEventListener(eventName, callback);
            });
        });
    }

    /**
     * 执行重连
     */
    _reconnect() {
        // 防止重连器重叠执行
        if (this._connectionState === EnhancedSSE.CONNECTION_STATES.RECONNECTING) {
            return;
        }
        
        this._changeState(EnhancedSSE.CONNECTION_STATES.RECONNECTING);
        
        // 检查最大重试次数
        if (this.retryCount >= this.options.maxRetries) {
            console.error('SSE连接失败次数超过上限，不再重连');
            this._changeState(EnhancedSSE.CONNECTION_STATES.FAILED);
            
            if (typeof this.options.onMaxRetries === 'function') {
                this.options.onMaxRetries();
            }
            return;
        }

        // 计算指数退避延迟
        this.retryCount++;
        const baseDelay = this.options.retryDelay * 
                         Math.pow(this.options.backoffFactor, this.retryCount - 1);
        const delay = Math.min(baseDelay, this.options.maxDelay);
        
        console.log(`SSE连接断开，${delay}ms后尝试第${this.retryCount}次重连`);

        // 设置重连定时器
        setTimeout(() => this.connect(), delay);
    }

    /**
     * 添加事件监听器
     * @param {string} eventName - 事件名称
     * @param {Function} callback - 回调函数
     */
    addEventListener(eventName, callback) {
        if (!this.listeners[eventName]) {
            this.listeners[eventName] = [];
        }
        
        // 防止重复添加回调
        if (!this.listeners[eventName].includes(callback)) {
            this.listeners[eventName].push(callback);
            
            if (this.eventSource) {
                this.eventSource.addEventListener(eventName, (event) => {
                    try {
                        // 解析数据并创建原始事件
                        const data = JSON.parse(event.data);
                        const rawEvent = new CustomEvent('sse-raw-event', { 
                            detail: { 
                                eventType: eventName,
                                eventData: event.data,
                                parsedData: data
                            }
                        });
                        document.dispatchEvent(rawEvent);
                        
                        // 执行原始回调
                        callback(event);
                    } catch (err) {
                        console.error(`处理 ${eventName} 事件出错:`, err);
                    }
                });
            }
        }
        
        return this; // 支持链式调用
    }

    /**
     * 移除事件监听器
     * @param {string} eventName - 事件名称
     * @param {Function} callback - 回调函数
     */
    removeEventListener(eventName, callback) {
        if (this.listeners[eventName]) {
            this.listeners[eventName] = this.listeners[eventName].filter(cb => cb !== callback);
            
            if (this.eventSource) {
                this.eventSource.removeEventListener(eventName, callback);
            }
        }
        
        return this; // 支持链式调用
    }

    /**
     * 关闭SSE连接
     */
    close() {
        this._aborted = true;
        this._closeEventSource();
        this.listeners = {};
        this._changeState(EnhancedSSE.CONNECTION_STATES.CLOSED);
        
        return this; // 支持链式调用
    }
}